package org.jeecg.modules.iot.middleware.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import org.jeecg.modules.iot.model.Consumption;
import org.jeecg.modules.iot.middleware.service.IConsumptionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
@DS("tdengine") // 保持与 LocationServiceImpl 一致的数据源
public class ConsumptionServiceImpl implements IConsumptionService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public int add(Consumption consumption) {
        return jdbcTemplate.update(
                "INSERT INTO " + consumption.getTableName() + " USING consumption TAGS (" + consumption.getDeviceId() + ") (ts, fMileage, eConsum,fPower) VALUES (?, ?, ?, ?)",
                consumption.getTs(), consumption.getFMileage(), consumption.getEConsum(), consumption.getFpower()
        );
    }


    @Override
    public Consumption queryByDeviceId(String deviceId) {
        try {
            String sql = "SELECT * FROM consumption WHERE device_id = ? ORDER BY ts DESC LIMIT 1";
            return jdbcTemplate.queryForObject(sql, new Object[]{deviceId}, new BeanPropertyRowMapper<>(Consumption.class));
        } catch (Exception e) {
            // 处理异常，例如返回null或抛出自定义异常
            return null;
        }
    }


    @Override
    public Consumption queryByFMileage(String deviceId, Float fMileage) {
        try {
            String sql = "SELECT * FROM consumption WHERE device_id = ? AND fMileage = ? ORDER BY ts DESC LIMIT 1";
            return jdbcTemplate.queryForObject(sql, new Object[]{deviceId, fMileage}, new BeanPropertyRowMapper<>(Consumption.class));
        } catch (Exception e) {
            // 处理异常，例如返回null或抛出自定义异常
            return null;
        }
    }

    //根据时间范围查询能耗数据
    @Override
    public List<Consumption> queryConsumptionsByTimeRange(String deviceId, Timestamp startTime, Timestamp endTime){
        String tableName = "c" + deviceId; // 注意表名
        String sql = "SELECT ts, fMileage, eConsum " +
                "FROM " + tableName + " " +
                "WHERE ts BETWEEN ? AND ? " +
                "ORDER BY ts ASC";

        try {
            return jdbcTemplate.query(sql, new Object[]{startTime, endTime}, new BeanPropertyRowMapper<>(Consumption.class));
        } catch (Exception e) {
            System.err.println("SQL query: " + sql);
            System.err.println("Parameters: startTime=" + startTime + ", endTime=" + endTime);
            // 处理异常，例如返回空列表或抛出自定义异常
            return new ArrayList<>(); // 或 throw new RuntimeException(...)
        }
    }

    @Override
    public Consumption queryLatestByDeviceId(String deviceId) {
        try {
            String sql = "SELECT * FROM consumption WHERE device_id = ? ORDER BY ts DESC LIMIT 1";
            return jdbcTemplate.queryForObject(sql, new Object[]{deviceId}, new BeanPropertyRowMapper<>(Consumption.class));
        } catch (EmptyResultDataAccessException e) {
            // 处理没有结果的情况
            return null;
        } catch (Exception e) {
            // 处理其他数据库访问异常
            throw new RuntimeException("Error querying latest consumption data for device: " + deviceId, e);
        }
    }


    @Override
    public Float calculateAverageEConsum(String deviceId, int n) {


        try {
            String sql = "SELECT eConsum FROM consumption WHERE device_id = ? ORDER BY ts DESC LIMIT ?";
            List<Float> eConsumList = jdbcTemplate.queryForList(sql, new Object[]{deviceId, n}, Float.class);

            if (eConsumList.isEmpty()) {
                return 0f; // 没有数据，返回 0
            }

            // 过滤掉 null
            eConsumList.removeIf(Objects::isNull);

            int size = eConsumList.size();
            if (size == 0) {
                return 0f;
            }

            // 计算均值
            float sum = 0;
            for (Float eConsum : eConsumList) {
                sum += eConsum;
            }
            float mean = sum / size;

            // 计算标准差
            float varianceSum = 0;
            for (Float eConsum : eConsumList) {
                varianceSum += Math.pow(eConsum - mean, 2);
            }
            float stdDev = (float) Math.sqrt(varianceSum / size);

            // 过滤掉偏差超过2倍标准差的数据
            List<Float> filteredList = new ArrayList<>();
            for (Float eConsum : eConsumList) {
                if (Math.abs(eConsum - mean) <= 2 * stdDev) {
                    filteredList.add(eConsum);
                }
            }

            // 计算过滤后的均值
            sum = 0;

            for (Float eConsum : filteredList) {
                sum += eConsum;
            }

            return sum / filteredList.size();

        } catch (Exception e) {
            throw new RuntimeException("Error calculating mean with std dev filter for device: " + deviceId, e);
        }
    }

    @Override
    public Float calculateMileageWeightedAverageEConsum(String deviceId, int n) {
        try {
            // 查询最近 n 条能耗数据
            String sql = "SELECT fMileage, eConsum FROM consumption WHERE device_id = ? ORDER BY ts DESC LIMIT ?";
            List<Map<String, Object>> resultList = jdbcTemplate.queryForList(sql, new Object[]{deviceId, n});

            if (resultList.isEmpty()) {
                return 0f; // 没有数据，返回 0
            }

            // 初始化加权总和和总权重
            float weightedSum = 0f;
            float totalMileage = 0f;

            // 遍历结果集，计算加权总和和总的行驶距离
            for (Map<String, Object> row : resultList) {
                Float fMileage = (Float) row.get("fMileage");
                Float eConsum = (Float) row.get("eConsum");
                if (fMileage ==0){
                    fMileage=100f;
                }
                // 过滤掉 null 以及行驶距离为 0 的数据
                if (fMileage != null && eConsum != null && fMileage > 0) {
                    weightedSum += eConsum * fMileage; // 值 * 权重
                    totalMileage += fMileage;           // 累加总权重（行驶距离）
                }
            }

            // 如果总行驶距离为 0，返回 0
            if (totalMileage == 0) {
                return 0f;
            }

            // 返回加权平均值
            return weightedSum / totalMileage;

        } catch (Exception e) {
            throw new RuntimeException("Error calculating mileage-weighted average for device: " + deviceId, e);
        }
    }


}
